/*
 * COPYRIGHT. ShenZhen JiMi Technology Co., Ltd. 2017.
 * ALL RIGHTS RESERVED.
 *
 * No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
 * on any form or by any means, electronic, mechanical, photocopying, recording, 
 * or otherwise, without the prior written permission of ShenZhen JiMi Network Technology Co., Ltd.
 *
 * Amendment History:
 * 
 * Date                   By              Description
 * -------------------    -----------     -------------------------------------------
 * 2017年4月24日    li.shangzhi         Create the class
 * http://www.jimilab.com/
 */

package com.jimi.gateway.filter.openapi.pre;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.jimi.app.dto.output.ApiOpenFunctionsOutputDto;
import com.jimi.exception.ErrorCode;
import com.jimi.framework.cache.redis.RedisUtil;
import com.jimi.framework.cache.redis.RedisUtil.ModuleType;
import com.jimi.gateway.utils.Constants;
import com.jimi.gateway.utils.ResultModel;
import com.jimi.web.dto.output.AccessTokenOutputDto;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

/**
 * @FileName AuthentificationFilter.java
 * @Description: 安全认证过滤，在RequestParamFilter过滤器后执行
 *
 * @Date 2017年4月24日 下午2:11:06
 * @author li.shangzhi
 * @version 1.0
 */
public class AuthentificationFilter extends ZuulFilter {

	private static final int FILTER_ORDER = 7;

	private final Logger logger = LoggerFactory.getLogger(AuthentificationFilter.class);

	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		String routeId = String.valueOf(ctx.get("proxy"));
		if (!Constants.OPEN_API_NAMESPACE.equals(routeId)) {
			return false;
		}
		// 如果前一个过滤器的结果为true，则说明上一个过滤器成功了，需要进入当前的过滤，如果前一个过滤器的结果为false，则说明上一个过滤器没有成功，则无需进行下面的过滤动作了，直接跳过后面的所有过滤器并返回结果
		return ctx.getBoolean(Constants.IS_NEXT_FILTER, true);
	}

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		ApiOpenFunctionsOutputDto outputDto = (ApiOpenFunctionsOutputDto) ctx.get(Constants.OPEN_FUNCTION);
		if (outputDto.getAuth()) { // 认证开关开启
			HttpServletRequest requeset = ctx.getRequest();
			String method = requeset.getParameter(Constants.METHOD);
			String appKey = requeset.getParameter(Constants.APP_KEY);
			// 其他Api请求
			String accessToken = requeset.getParameter("access_token");
			if (StringUtils.isBlank(accessToken)) {
				logger.info("【安全认证】用户AppKey：{}，请求方法名：{}，access_token参数不存在", appKey, method);
				ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
				ctx.setResponseStatusCode(401);// 返回错误码
				ctx.setResponseBody(JSONObject.toJSONString(new ResultModel(ErrorCode.TOKEN_ERROR)));
				ctx.set(Constants.IS_NEXT_FILTER, false);// 后续的过滤器是否继续执行
				return null;
			}
			String jsonStr = RedisUtil.getString(ModuleType.OAUTH, accessToken);
			if (StringUtils.isBlank(jsonStr)) {
				logger.info("【安全认证】用户AppKey：{}，请求方法名：{}，access_token值：{}，在redis中不存在", appKey, method, accessToken);
				ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
				ctx.setResponseStatusCode(401);// 返回错误码
				ctx.setResponseBody(JSONObject.toJSONString(new ResultModel(ErrorCode.TOKEN_ERROR)));
				ctx.set(Constants.IS_NEXT_FILTER, false);// 后续的过滤器是否继续执行
				return null;
			} else {
				AccessTokenOutputDto accessTokenOutputDto = JSONObject.parseObject(jsonStr, AccessTokenOutputDto.class);
				ctx.set(Constants.USE_ACCOUNT, accessTokenOutputDto.getAccount());
			}
		} else {
			logger.info("请求方法：{}，认证开关：{}", outputDto.getMethod(), outputDto.getAuth());
		}
		ctx.set(Constants.IS_NEXT_FILTER, true);// 后续的过滤器是否继续执行
		return null;
	}

	@Override
	public String filterType() {
		return Constants.PRE_FILTER;
	}

	@Override
	public int filterOrder() {
		return FILTER_ORDER;
	}
}
